/**
 * 7、兼容性
 * TS 中的兼容性，主要看结构是否兼容。（核心是考虑安全性）
 */
/**
 * 一、基本数据类型的兼容性
 */
let temp: string | number;
let num3!: number;
temp = num3;

/**
 * 二、接口兼容性
 */
interface IAnimal3 {
    name: string,
    age: number
}
interface IPerson {
    name: string,
    age: number,
    address: string
}
let animal2: IAnimal3;
let person4: IPerson = {
    name: "dada",
    age: 11,
    address: "大大街"
};
animal2 = person4;
// 接口的兼容性，只要满足接口中所需要的类型即可

/**
 * 三、函数的兼容性
 */
// 函数的兼容性主要是比较参数和返回值
// 参数
let sum5 = (a: string, b: string) => a + b;
let sum6 = (a: string) => a;
sum5 = sum6;
// 赋值函数的参数要少于等于被赋值的函数，与对象相反，例如：
type Func<T> = (item: T, index: number) => void;
function forEach<T>(arr: T[], cb: Func<T>) {
    for (let i = 0; i < arr.length; i++) {
        cb(arr[i], i);
    }
}
forEach([1, 2, 3], (item) => {
    console.log(item);
});

// 返回值
type sum7 = () => string | number;
type sum8 = () => string;
let fn1: sum7;
let fn2!: sum8;
fn1 = fn2;

/**
 * 四、函数的逆变与协变
 * 函数的参数是逆变的，返回值是协变的（在非严格模式下函数的参数是双向协变的）
 */
class Parent {
    address: string = "大大地址";
}
class Child extends Parent {
    money: number = 100;
}
class Grandsom extends Child {
    name: string = "溜溜";
}
type Callback = (person: Child) => Child;
function execCallback(cb: Callback) {}
let fn3 = (person: Parent) => new Grandsom();
execCallback(fn3);

/**
 * 五、类的兼容性
 */
class Perent {
    name: string = 'dada';
    age: number = 11;
}
class Perent1 {
    name: string = "123";
    age: number = 11;
}
let parent2: Perent = new Perent1()
